! VSemiletov, 08.2011
subroutine OutputTransducerData()
use Data_cfoam, only: ZeroEpsilon, rank, nump, processor, ie, ierr, &
                      Pnew,P, Unew,U, Tnew,T, ZeroEpsilon, Us,Usnew, ps,psnew, Rhos,Rhosnew
use DataTime, only: nstep, ttime, dt=>dt2
use Data_Mesh, only: nCells, nFaces
use Data_Transducer
implicit none
include 'mpif.h'

    real(8),allocatable :: Send(:)
!    real(8) :: TimeGlobal, TimeOut
    integer :: i,j, iTrans, iVar
    real(8) :: alfa, beta
    
    real(8) :: timeCurrent,timeFormer, timeOut,timeOutFormer, timeAverage
    integer :: n, ii
    
    character(280) :: name
    integer :: nameLenght
    integer :: OpenFile,gfpos(1:nTransducers*nump),fpos(1:nTransducers), &
               dpextent, iextent, fout
    integer(kind=MPI_OFFSET_KIND) :: fdispl,fdispl2
    
    ierr=0
    fdispl2=0
! setup and calculation of the offsets
!    call MPI_TYPE_EXTENT deprecated
    call MPI_TYPE_SIZE(MPI_INTEGER, iextent, ierr)
    call MPI_TYPE_SIZE(MPI_DOUBLE_PRECISION, dpextent, ierr)

!   sending arrays definition
!   calculate offsets for MPI-IO
    fpos=0
    do i = 1,nTransducers
       fpos(i)=fpos(i)+(Transducer(i)%nCellsOut*Transducer(i)%nVars*dpextent) + (2*iextent) + dpextent
    end do

    call MPI_Allgather( fpos, nTransducers, MPI_INT, gfpos, &
                        nTransducers, MPI_INT, MPI_COMM_WORLD,ierr)

    call MPI_Barrier(MPI_COMM_WORLD,ierr)

    fdispl=0

    if (rank>0) then
    do j = 0,rank
      do i = 1, nTransducers
        fdispl = fdispl + gfpos(nTransducers*(j-1)+i)
      end do
    end do
    endif 

!   end of calculation for the offsets

    
    do iTrans = 1,nTransducers
   
        if(ttime-Transducer(iTrans)%TimeStart.lt.ZeroEpsilon.or. &
           ttime.gt.Transducer(iTrans)%TimeEnd) cycle

        timeCurrent = ttime - Transducer(iTrans)%TimeStart
        timeFormer = timeCurrent - dt

        n = max(0,int(timeFormer / Transducer(iTrans)%dTimeOut))
        timeOutFormer = n * Transducer(iTrans)%dTimeOut !+ Transducer(iTrans)%TimeStart
        timeOut = (n+1) * Transducer(iTrans)%dTimeOut !+ Transducer(iTrans)%TimeStart

        timeAverage = max(0.0d0,timeFormer-timeOutFormer) ! timeAverage = max(0.0d0,timeFormer-timeOut)

!        if(timeFormer.lt.0.0d0)then
        if(timeOutFormer.gt.timeFormer)then
!            alfa = abs(timeFormer) / dt
!            alfa = (dt - (Transducer(iTrans)%TimeStart - timeFormer)) / dt
            alfa = (timeOutFormer - timeFormer) / dt
        else
            alfa = 0.0d0
        end if

        if(timeOut.lt.timeCurrent)then
            beta = (timeOut - timeFormer) / dt
        else
            beta = 1.0d0
        end if
        
        if(Transducer(iTrans)%SliceOut)then ! poka zaplatka: osrednyaem tol'ko se4eniya, NOTE: VSemiletov
            if(Transducer(iTrans)%Average)then
!                call AddVarsToAverageArray(alfa,beta,dt,timeAverage)
                call AddVarsToAverageArray(alfa,beta,dt,timeAverage, nCells, &
                                           Transducer(iTrans)%nCellsOut, &
                                           Transducer(iTrans)%CellsOut, &
                                           Transducer(iTrans)%Vars, &
                                           U,Unew, p,pnew, T,Tnew)

                call AddVarsToAverageArray(alfa,beta,dt,timeAverage, nFaces, &
                                           Transducer(iTrans)%nFacesOut, &
                                           Transducer(iTrans)%FacesOut, &
                                           Transducer(iTrans)%VarsFace, &
                                           Us,Usnew, ps,psnew, Rhos,Rhosnew)
            end if
        end if
!      Transducer(iTrans)%EveryStep=.TRUE.
!        if(beta.lt.1.0d0+ZeroEpsilon.or.Transducer(iTrans)%EveryStep)then ! Output
        if(timeOut.lt.timeCurrent+ZeroEpsilon.or.Transducer(iTrans)%EveryStep)then ! Output
            Transducer(iTrans)%ndTimeOut = Transducer(iTrans)%ndTimeOut + 1

            ! Slice output
            if(Transducer(iTrans)%SliceOut)then

!                if(rank.eq.0.and.Transducer(iTrans)%EveryStep.eqv..false.)then
!                    write(*,'(a11,a20,a13,f20.10)') 'Transducer ', Transducer(iTrans)%Name, ' output, Time=', timeOut
!                end if

                if(Transducer(iTrans)%Average.eqv..false.)then
                    do j = 1,3    ! Velocities Output
                        do i = 1,Transducer(iTrans)%nCellsOut
                            ii = Transducer(iTrans)%CellsOut(i)
                            Transducer(iTrans)%Vars(i,j) = (1.0d0-beta) * U(j,ii) + beta * Unew(j,ii)
                        end do
                    end do
                    do i = 1,Transducer(iTrans)%nCellsOut
                        ii = Transducer(iTrans)%CellsOut(i)
                        Transducer(iTrans)%Vars(i,4) = (1.0d0-beta) * p(ii) + beta * pnew(ii)
                    end do
                    do i = 1,Transducer(iTrans)%nCellsOut
                        ii = Transducer(iTrans)%CellsOut(i)
                        Transducer(iTrans)%Vars(i,5) = (1.0d0-beta) * T(ii) + beta * Tnew(ii)
                    end do
                end if

                if(Transducer(iTrans)%dPdtOut)then
                    do i = 1,Transducer(iTrans)%nCellsOut
                        ii = Transducer(iTrans)%CellsOut(i)
                        Transducer(iTrans)%Vars(i,6) = (pnew(ii) - p(ii)) / dt
                    end do
                end if

                timeAverage = timeAverage + beta * dt
                if(Transducer(iTrans)%AllProcsWriteOwnData)then
                    open(1,file=Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength), &
                            form='unformatted',position='append',IOSTAT=OpenFile)
                    if (OpenFile.ne.0) then
                        write(*,*) '@@ Fatal Error: File open error ', &
                                Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength)
                        STOP '@@ Fatal Error!'
                    end if
!                    write(1) timeOut+Transducer(iTrans)%TimeStart, &
!                             Transducer(iTrans)%nVars,Transducer(iTrans)%nCellsOut

                else
                    if(rank.eq.0)then
                        name(1:Transducer(iTrans)%nameLength) = Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength)
                        nameLenght = Transducer(iTrans)%nameLength + 4
                        name(nameLenght-3:nameLenght) = 'Face'
                        if(Transducer(iTrans)%ndTimeOut.eq.1)then
                            open(1,file=Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength), &
                                    form='unformatted',IOSTAT=OpenFile)
                            if (OpenFile.ne.0) then
                                write(*,*) '@@ Fatal Error: File open error ', &
                                        Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength)
                                STOP '@@ Fatal Error!'
                            end if

                            open(2,file=name(1:nameLenght),form='unformatted',IOSTAT=OpenFile)
                            if (OpenFile.ne.0) then
                                write(*,*) '@@ Fatal Error: File open error ', name(1:nameLenght)
                                STOP '@@ Fatal Error!'
                            end if
                        else
                            open(1,file=Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength), &
                                    form='unformatted',position='append',IOSTAT=OpenFile)
                            if (OpenFile.ne.0) then
                                write(*,*) '@@ Fatal Error: File open error ', &
                                        Transducer(iTrans)%fileOutput(1:Transducer(iTrans)%nameLength)
                                STOP '@@ Fatal Error!'
                            end if

                            open(2,file=name(1:nameLenght),form='unformatted',position='append', &
                                        IOSTAT=OpenFile)
                            if (OpenFile.ne.0) then
                                write(*,*) '@@ Fatal Error: File open error ', name(1:nameLenght)
                                STOP '@@ Fatal Error!'
                            end if
                        end if
                    end if
                    
!                    write(1) timeOut+Transducer(iTrans)%TimeStart, &
!                             Transducer(iTrans)%nVars,Transducer(iTrans)%nCellsOutGlobal
!                    write(2) timeOut+Transducer(iTrans)%TimeStart, nstep+1,timeAverage, &
!                             Transducer(iTrans)%nVars,Transducer(iTrans)%nFacesOutGlobal
                end if
                if(Transducer(iTrans)%AllProcsWriteOwnData)then
! need to uncomment cycle part -- 2 lines at the top of loop, and remove setting
! of Transducer(iTrans)%EveryStep=.TRUE.
                     ii=Transducer(iTrans)%nameLength-15
                     call MPI_FILE_OPEN(MPI_COMM_WORLD,Transducer(iTrans)%fileOutput(ii:Transducer(iTrans)%nameLength),&
                               MPI_MODE_WRONLY + MPI_MODE_APPEND, MPI_INFO_NULL, fout, ierr)
                     call MPI_FILE_GET_POSITION(fout, fdispl2, ierr)
                     call MPI_FILE_SEEK(fout,fdispl+fdispl2, MPI_SEEK_SET,ierr)
                     call MPI_FILE_WRITE_ALL(fout,timeOut+Transducer(iTrans)%TimeStart ,1, MPI_DOUBLE_PRECISION, &
                                MPI_STATUS_IGNORE, ierr)
                     call MPI_FILE_WRITE_ALL(fout,  Transducer(iTrans)%nVars, 1, MPI_INTEGER, &
                                MPI_STATUS_IGNORE, ierr)
                     call MPI_FILE_WRITE_ALL(fout,  Transducer(iTrans)%nCellsOut, 1, MPI_INTEGER, &
                                MPI_STATUS_IGNORE, ierr)
                     ii = Transducer(iTrans)%nVars*Transducer(iTrans)%nCellsOut
                     call MPI_FILE_WRITE_ALL(fout,  Transducer(iTrans)%Vars, ii, MPI_DOUBLE_PRECISION, &
                                MPI_STATUS_IGNORE, ierr)
                     call MPI_FILE_CLOSE(fout,ierr)

                    write(1) timeOut+Transducer(iTrans)%TimeStart, Transducer(iTrans)%nVars,Transducer(iTrans)%nCellsOut
                    write(1) ((Transducer(iTrans)%Vars(i,ii),ii=1,Transducer(iTrans)%nVars),i=1,Transducer(iTrans)%nCellsOut)
                else
                    write(1) timeOut+Transducer(iTrans)%TimeStart, &
                             Transducer(iTrans)%nVars,Transducer(iTrans)%nCellsOutGlobal
                    write(2) timeOut+Transducer(iTrans)%TimeStart, nstep+1,timeAverage, &
                             Transducer(iTrans)%nVars,Transducer(iTrans)%nFacesOutGlobal

                    do i = 1,Transducer(iTrans)%nVars
                        call OutputArray(Transducer(iTrans)%Vars(:,i),Transducer(iTrans)%nCellsOut, &
                                         Transducer(iTrans)%recv,Transducer(iTrans)%recvCounts,Transducer(iTrans)%rDispls, &
                                         Transducer(iTrans)%nCellsOutGlobal,1)
    !
                        call OutputArray(Transducer(iTrans)%VarsFace(:,i),Transducer(iTrans)%nFacesOut, &
                                         Transducer(iTrans)%recvFace,Transducer(iTrans)%recvCountsFace, &
                                         Transducer(iTrans)%rDisplsFace, &
                                         Transducer(iTrans)%nFacesOutGlobal,2)
                    end do
                end if

                if(rank.eq.0)then
                    close(1)
                    close(2)
                end if

                if(Transducer(iTrans)%Average)then
                    do j = 1,5
                        do i = 1,Transducer(iTrans)%nCellsOut
                            Transducer(iTrans)%Vars(i,j) = 0.0d0
                            timeAverage = 0d0
                        end do
                    end do
                    call AddVarsToAverageArray(beta,1.0d0,dt,timeAverage, nCells, &
                           Transducer(iTrans)%nCellsOut, &
                           Transducer(iTrans)%CellsOut, &
                           Transducer(iTrans)%Vars, &
                           U,Unew, p,pnew, T,Tnew)
!                    call AddVarsToAverageArray(beta,1.0d0,dt,timeAverage)
                    call AddVarsToAverageArray(beta,1.0d0,dt,timeAverage, nFaces, &
                           Transducer(iTrans)%nFacesOut, &
                           Transducer(iTrans)%FacesOut, &
                           Transducer(iTrans)%VarsFace, &
                           Us,Usnew, ps,psnew, Rhos,Rhosnew)
                end if

!                end if ! if(Transducer(iTrans)%AllProcsWriteOwnData)then

            end if
            
            ! Table output
            if(Transducer(iTrans)%TableOut)then

                if(Transducer(iTrans)%EveryStep)then ! for tableOut only
                    beta = 1d0
                    TimeOut = ttime
                end if
                
                if(rank.eq.0)then
                    open(1,file=Transducer(iTrans)%fileOutput,position='append')
!                    write(1,'(f25.15)',ADVANCE = 'NO') TimeOut ! \)',ADVANCE = 'NO') TimeOut
                    write(1,'(f25.15)',ADVANCE = 'NO') TimeOut + Transducer(iTrans)%TimeStart
                    write(1,'(a3)',ADVANCE = 'NO') ' | ' ! \)',ADVANCE = 'NO') ' | '
                end if

                alfa = beta ! (TimeGlobal - TimeOut) / Transducer(iTrans)%dTimeOut

                allocate(Send(nCells))
                if(Transducer(iTrans)%Pres)then
                    call OutputScalarTransducer(pnew,p,iTrans,Send,alfa)
                end if
                if(Transducer(iTrans)%Uvel)then
                    call OutputVectorTransducer(Unew,U,iTrans,Send,alfa,1)
                end if
                if(Transducer(iTrans)%Vvel)then
                    call OutputVectorTransducer(Unew,U,iTrans,Send,alfa,2)
                end if
                if(Transducer(iTrans)%Wvel)then
                    call OutputVectorTransducer(Unew,U,iTrans,Send,alfa,3)
                end if
                if(Transducer(iTrans)%Temp)then
                    call OutputScalarTransducer(Tnew,T,iTrans,Send,alfa)
                end if

                if(rank.eq.0)then
                    write(1,'(a1)') ' '
    !                write(1,*) ' ' ! for desk top VSemiletov
                    close(1)
                end if

                deallocate(Send)
            end if
        end if
    end do

contains

    subroutine AddVarsToAverageArray(alfa,beta,dt,timeAverage, n, nOut,Out, Vars, U,Unew, p,pnew, T,Tnew)
    implicit none
        real(8),intent(in) :: alfa,beta,dt,timeAverage
        integer,intent(in) :: n, nOut, Out(nOut)
        real(8),intent(in) :: U(3,n),Unew(3,n), p(n),pnew(n), T(n),Tnew(n)
        real(8),intent(inout) :: Vars(nOut,5)

        do j = 1,3    ! Velocities Output
            do i = 1,nOut
                ii = Out(i)
                call AddVarsToAverageVal(Vars(i,j),U(j,ii),Unew(j,ii),alfa,beta,dt,timeAverage)
            end do
        end do
        do i = 1,nOut
            ii = Out(i)
            call AddVarsToAverageVal(Vars(i,4),p(ii),pnew(ii),alfa,beta,dt,timeAverage)
        end do
        do i = 1,nOut
            ii = Out(i)
            call AddVarsToAverageVal(Vars(i,5),T(ii),Tnew(ii),alfa,beta,dt,timeAverage)
        end do

    end subroutine AddVarsToAverageArray

    ! the time integration of the solution by the trapezoidal
    subroutine AddVarsToAverageVal(AverageVal,Val1,Val2,alfa,beta,dt,timeAverage)
    use Data_cfoam, only: ZeroEpsilon
    implicit none
        real(8),intent(inout) :: AverageVal
        real(8),intent(in) :: Val1,Val2,alfa,beta,dt,timeAverage

        real(8) :: Val, timeVal
        
        Val = Val1 + 0.5 * (alfa + beta) * (Val2-Val1)
        timeVal = dt * (beta - alfa)
        
        if(timeAverage + timeVal.lt.ZeroEpsilon)then
            return
        end if
        AverageVal = (AverageVal * timeAverage + Val * timeVal) / (timeAverage + timeVal)

    end subroutine AddVarsToAverageVal

end subroutine OutputTransducerData


subroutine OutputScalarTransducer(ArrNew,Arr,iTrans,Send,alfa)
use Data_cfoam, only: rank,ierr
use Data_Mesh, only: nCells
use Data_Transducer
implicit none
include 'mpif.h'
    real(8),intent(in) :: ArrNew(nCells), Arr(nCells)
    integer,intent(in) :: iTrans
    real(8),intent(inout) :: Send(nCells)
    real(8),intent(in) :: alfa

    integer :: i
    
    do i = 1,Transducer(iTrans)%nCellsOut
        Send(i) = (1.0d0-alfa) * Arr(Transducer(iTrans)%CellsOut(i)) + alfa * ArrNew(Transducer(iTrans)%CellsOut(i))
        if(rank.eq.0)then
            Transducer(iTrans)%recv(i) = Send(i) ! 0.0d0
        end if
    end do

    if(rank.gt.0)then
        call MPI_Gatherv(Send,Transducer(iTrans)%nCellsOut,MPI_DOUBLE_PRECISION,Transducer(iTrans)%recv, &
                     Transducer(iTrans)%recvCounts,Transducer(iTrans)%rDispls, &
                     MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)
    end if

    if(rank.eq.0)then
        do i = 1,Transducer(iTrans)%nCellsOutGlobal
            write(1,'(f25.15)',ADVANCE = 'NO') Transducer(iTrans)%recv(i) ! \)',ADVANCE = 'NO') Transducer(iTrans)%recv(i)
        end do
        write(1,'(a3)',ADVANCE = 'NO') ' | ' ! \)',ADVANCE = 'NO') ' | '
    end if

end subroutine OutputScalarTransducer


subroutine OutputVectorTransducer(ArrNew,Arr,iTrans,Send,alfa,index)
use Data_cfoam, only: rank,ierr
use Data_Mesh, only: nCells
use Data_Transducer
implicit none
include 'mpif.h'
    real(8),intent(in) :: ArrNew(3,nCells), Arr(3,nCells)
    integer,intent(in) :: iTrans, index
    real(8),intent(inout) :: Send(nCells)
    real(8),intent(in) :: alfa

    integer :: i
    
    do i = 1,Transducer(iTrans)%nCellsOut
        Send(i) = (1.0d0-alfa) * Arr(index,Transducer(iTrans)%CellsOut(i)) + alfa * ArrNew(index,Transducer(iTrans)%CellsOut(i))
        if(rank.eq.0)then
            Transducer(iTrans)%recv(i) = 0.0d0
        end if
    end do

    call MPI_Gatherv(Send,Transducer(iTrans)%nCellsOut,MPI_DOUBLE_PRECISION,Transducer(iTrans)%recv, &
                     Transducer(iTrans)%recvCounts,Transducer(iTrans)%rDispls, &
                     MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)

    if(rank.eq.0)then
        do i = 1,Transducer(iTrans)%nCellsOutGlobal
            write(1,'(f25.15)',ADVANCE = 'NO') Transducer(iTrans)%recv(i) ! \)',ADVANCE = 'NO') Transducer(iTrans)%recv(i)
        end do
        write(1,'(a3)',ADVANCE = 'NO') ' | ' ! \)',ADVANCE = 'NO') ' | '
    end if

end subroutine OutputVectorTransducer
